package com.atguigu.spring5_webflux.handler;

import com.atguigu.spring5_webflux.entity.User;
import com.atguigu.spring5_webflux.service.UserService;
import org.springframework.http.MediaType;
import org.springframework.web.reactive.function.server.ServerRequest;
import org.springframework.web.reactive.function.server.ServerResponse;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import static org.springframework.web.reactive.function.BodyInserters.fromObject;

/**
 * 基于函数式编程模型的实现，创建handler具体操作
 */
public class UserHandler {

    private final UserService userService;

    // 非注解方式，通过有参构造引用userService
    public UserHandler(UserService userService) {
        this.userService = userService;
    }

    /**
     * 根据ID查询
     * SpringWebflux请求和响应不再是springmvc中的ServletRequest和ServletResponse，而是ServerRequest和ServerResponse。
     * @param request
     * @return
     */
    public Mono<ServerResponse> getUserById(ServerRequest request){
        // 获取ID值
        int userId = Integer.valueOf(request.pathVariable("id"));
        // 构建一个空值响应
        Mono<ServerResponse> notFound = ServerResponse.notFound().build();
        Mono<User> userMono = this.userService.getUserById(userId);
        // userMono进行转换，转为流ServerResponse，进行返回
        // Reactor.flatMap  把每个元素转换流，把转换之后多个流合并为更大的流。
        // ServerResponse.ok() 表示操作成功
        // contentType 表示返回类型
        return userMono.flatMap(person -> ServerResponse.ok()
                .contentType(MediaType.APPLICATION_JSON)
                .body(fromObject(person))) // 对象转化为 BodyInserter
                .switchIfEmpty(notFound); // 当id值为空时，返回给前端一个空值响应
    }

    /**
     * 查询所有
     * 返回的是serverResponse，就一个所以是mono，flux<users>被封装到serverResponse的body中
     * 请求参数必须加上 ServerRequest request ，尽管可能用不到
     * @return
     */
    public Mono<ServerResponse> getAllUsers(ServerRequest request){
        Flux<User> users = this.userService.getAllUser();
        return ServerResponse.ok().contentType(MediaType.APPLICATION_JSON).body(users,User.class);  // 与上面的 userMono.flatMap 效果一样
    }


    /**
     * 添加
     * @param request
     * @return
     */
    public Mono<ServerResponse> saveUser(ServerRequest request){
        Mono<User> userMono = request.bodyToMono(User.class);
        // bulid 表示订阅目标操作，发生变化后收到通知
        return ServerResponse.ok().build(this.userService.saveUserInfo(userMono));
    }



}
